use std::net::{Ipv4Addr, Ipv6Addr};
use ipnet::{IpNet, Ipv4Net, Ipv4Subnets, Ipv6AddrRange};

// 将现有 IP 网络细分为更小的子网
#[test]
fn test_ipv4network_subdivide_smaller_subnet() {
    let net: Ipv4Net = "192.168.0.0/23".parse().unwrap();

    println!("\n/25 subnets in {}:", net);

    // Note: `subnets()` returns a `Result`. If the given prefix length
    // is less than the existing prefix length the `Result` will contain
    // an error.

    let subnets = net.subnets(25)
        .expect("PrefixLenError: new prefix length cannot be shorter than existing");

    // Output:
    //  subnet 0 = 192.168.0.0/25
    //  subnet 1 = 192.168.0.128/25
    //  subnet 2 = 192.168.1.0/25
    //  subnet 3 = 192.168.1.128/25

    for (i, n) in subnets.enumerate() {
        println!("\tsubnet {} = {}", i, n);
    }
}


#[test]
// 迭代两个 IPv4 地址之间的有效子网
fn test_iterate_over_valid_subnets() {
    let start = Ipv4Addr::new(10, 0, 0, 0);
    let end = Ipv4Addr::new(10, 0, 0, 239);

    println!("\n/0 or greater subnets between {} and {}:", start, end);

    // Output all subnets starting with the largest that will fit. This
    // will give us the smallest possible set of valid subnets.
    //
    // Output:
    //  subnet 0 = 10.0.0.0/25
    //  subnet 1 = 10.0.0.128/26
    //  subnet 2 = 10.0.0.192/27
    //  subnet 3 = 10.0.0.224/28

    let subnets = Ipv4Subnets::new(start, end, 0);

    for (i, n) in subnets.enumerate() {
        println!("\tsubnet {} = {}", i, n);
    }

    println!("\n/26 or greater subnets between {} and {}:", start, end);

    // Output all subnets with prefix lengths less than or equal to 26.
    // This results in more subnets, but limits them to a maximum size.
    //
    // Output:
    //  subnet 0 = 10.0.0.0/26
    //  subnet 1 = 10.0.0.64/26
    //  subnet 2 = 10.0.0.128/26
    //  subnet 3 = 10.0.0.192/27
    //  subnet 4 = 10.0.0.224/28

    let subnets = Ipv4Subnets::new(start, end, 26);

    for (i, n) in subnets.enumerate() {
        println!("\tsubnet {} = {}", i, n);
    }
}


#[test]
fn test_ipv6AddrRange() {
    let hosts = Ipv6AddrRange::new(
        "fd00::".parse().unwrap(),
        "fd00::3".parse().unwrap(),
    );

    let res = hosts.collect::<Vec<Ipv6Addr>>();
    res.iter().for_each(|host| println!("{}", host));

    hosts.for_each(|host| println!("host addr = {}", host));
}